package net.tomblog.app.swingheil.provider;

import java.util.Date;

import net.tomblog.app.swingheil.model.Article;
import net.tomblog.app.swingheil.util.L;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;


/**
 * Article Provider
 * 
 * @author hyunung.park (parkbear01@gmail.com)
 *
 */
public class ArticleProvider extends ContentProvider {

	private final String TAG = "ArticleProvider";
	
    private static final String DATABASE_NAME = "articles.db";
    private static final int DATABASE_VERSION = 1;
    
    public static final String UPDATED = "updated";
    public static final String INSERTED = "inserted";

    private static final int ARTICLE_ID = 1;
    private static final int ARTICLES = 2;
    
    private static final String TABLE = "articles";
	private static final String CREATE_TABLE = "CREATE TABLE " + TABLE + " (" 
		+ Article._ID + " INTEGER PRIMARY KEY, " 
		+ Article.BOARD_ID + " TEXT, " 
		+ Article.ARTICLE_ID + " INTEGER, " 
		+ Article.ARTICLE_TITLE + " TEXT, " 
		+ Article.NICKNAME + " TEXT, " 
		+ Article.WRITE_DATE + " LONG, " 
		+ Article.COMMENT_COUNT + " INTEGER, " 
		+ Article.READ_COUNT + " INTEGER, " 
		+ Article.CAFE_ID + " TEXT, " 
		+ Article.HIDDEN + " INTEGER, " 
		+ Article.NEW_ARTICLE + " INTEGER)";

    private static final UriMatcher URI_MATCHER;
    static {
        URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
        URI_MATCHER.addURI(Article.AUTHORITY, "articles", ARTICLES);
        URI_MATCHER.addURI(Article.AUTHORITY, "articles/#", ARTICLE_ID);
    }
    
    private SQLiteOpenHelper mOpenHelper;
    
	@Override
	public boolean onCreate() {
		L.d(TAG, " >>> called onCreate()");
        mOpenHelper = new DatabaseHelper(getContext());
        return true;
	}
	
	@Override
	public String getType(Uri uri) {
        switch (URI_MATCHER.match(uri)) {
        case ARTICLES:
            return "vnd.android.cursor.dir/vnd.net.tomblog.swingheil.article";
        case ARTICLE_ID:
            return "vnd.android.cursor.item/vnd.net.tomblog.swingheil.article";
        default:
            throw new IllegalArgumentException("Unknown URI " + uri);
        }
	}
	
	@Override
	public Uri insert(Uri uri, ContentValues values) {

		if (URI_MATCHER.match(uri) != ARTICLES) {
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		// 같은 글이 있는지 확인하여, 있다면 update
		// (CAFE_ID, BOARD_ID, ARTICLE_ID로 판단)
		String cafeId = values.getAsString(Article.CAFE_ID);
		String boardId = values.getAsString(Article.BOARD_ID);
		Integer articleId = values.getAsInteger(Article.ARTICLE_ID);
		
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
        qb.setTables(TABLE);
        qb.appendWhere(Article.CAFE_ID + "='" + cafeId + "'");
        qb.appendWhere(" AND " + Article.BOARD_ID + "='" + boardId + "'");
        qb.appendWhere(" AND " + Article.ARTICLE_ID + "='" + articleId + "'");
        Cursor cursor = qb.query(db, null, null, null, null, null, null);
		if(cursor.getCount() > 0 && cursor.moveToFirst()) {
			String id = cursor.getString(cursor.getColumnIndex(Article._ID));
			Uri updateUri = Uri.withAppendedPath(Article.CONTENT_URI, id);
			update(updateUri, values, null, null);
//			L.d(TAG, "updated : " + updateUri.toString());
			updateUri = Uri.withAppendedPath(updateUri, UPDATED);
			updateUri = Uri.withAppendedPath(updateUri, String.valueOf(articleId));
			return updateUri;
		}
        
		// 새로운 글이라면 insert
        final long rowId = db.insert(TABLE, null, values);
        if (rowId > 0) {
            Uri insertUri = ContentUris.withAppendedId(Article.CONTENT_URI, rowId);
            getContext().getContentResolver().notifyChange(uri, null);
            insertUri = Uri.withAppendedPath(insertUri, INSERTED);
            insertUri = Uri.withAppendedPath(insertUri, String.valueOf(articleId));
            return insertUri;
        }

        throw new SQLException("Failed to insert row into " + uri);
	}
	
	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder qb = new SQLiteQueryBuilder();

        switch (URI_MATCHER.match(uri)) {
            case ARTICLES:
                qb.setTables(TABLE);
                break;
            case ARTICLE_ID:
                qb.setTables(TABLE);
                qb.appendWhere("_id=" + uri.getPathSegments().get(1));
                break;
            default:
                throw new IllegalArgumentException("Unknown URI " + uri);
        }
        
        String orderBy;
        if (TextUtils.isEmpty(sortOrder)) {
            orderBy = Article.DEFAULT_SORT_ORDER;
        } else {
            orderBy = sortOrder;
        }
        
        SQLiteDatabase db = mOpenHelper.getReadableDatabase();
        Cursor cursor = qb.query(db, projection, selection, selectionArgs, null, null, orderBy);
        cursor.setNotificationUri(getContext().getContentResolver(), uri);

        return cursor;
	}
	
	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
	     SQLiteDatabase db = mOpenHelper.getWritableDatabase();
	     
		int count = 0;
		switch (URI_MATCHER.match(uri)) {
		case ARTICLES:
			count = db.update(TABLE, values, selection, selectionArgs);
			break;
		case ARTICLE_ID:
			count = db.update(TABLE, values, Article._ID
					+ " = "
					+ uri.getPathSegments().get(1)
					+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
							+ ')' : ""), selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}
		
		getContext().getContentResolver().notifyChange(uri, null);

		return count;
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();

        int count = 0;
		switch (URI_MATCHER.match(uri)) {
		case ARTICLES:
			count = db.delete(TABLE, selection, selectionArgs);
			break;
		case ARTICLE_ID:
			String segment = uri.getPathSegments().get(1);
			count = db.delete(TABLE, Article._ID
					+ "="
					+ segment
					+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
							+ ')' : ""), selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI " + uri);
		}

        getContext().getContentResolver().notifyChange(uri, null);

        return count;
	}
	
	private static class DatabaseHelper extends SQLiteOpenHelper {
		private final String TAG = "DatabaseHelper";

		DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL(CREATE_TABLE);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			L.w(TAG, "Upgrading database from version " + oldVersion + " to "
					+ newVersion + ", which will destroy all old data");

			db.execSQL("DROP TABLE IF EXISTS books");
			onCreate(db);
		}
	}
	
	/**
	 * Content Provider에 데이터 삽입을 위한 변환 메소드
	 * @param article
	 * @return
	 */
	public static ContentValues getContentValuesFromArticle(Article article) {
		ContentValues values = new ContentValues();
		
		values.put(Article.BOARD_ID, article.getBoardId());
		values.put(Article.ARTICLE_ID, article.getArticleId());
		values.put(Article.ARTICLE_TITLE, article.getArticleTitle());
		values.put(Article.NICKNAME, article.getNickname());
		values.put(Article.WRITE_DATE, article.getWriteDate().getTime());
		values.put(Article.COMMENT_COUNT, article.getCommentCount());
		values.put(Article.READ_COUNT, article.getReadCount());
		values.put(Article.CAFE_ID, article.getCafeId());
		int isHidden = (article.isHidden() == true) ? 1 : 0;
		values.put(Article.HIDDEN, isHidden);
		int newArticle = (article.isNewArticle() == true) ? 1 : 0;
		values.put(Article.NEW_ARTICLE, newArticle);
		
		return values;
	}
	
	/**
	 * Cursor에서 Article객체를 반환
	 * @param cursor
	 * @return
	 */
	public static Article getArticleFromCursor(Cursor cursor) {
		Article article = new Article();
		
		article.setBoardId(cursor.getString(cursor.getColumnIndex(Article.BOARD_ID)));
		article.setArticleId(Integer.parseInt(cursor.getString(cursor.getColumnIndex(Article.ARTICLE_ID))));		
		article.setArticleTitle(cursor.getString(cursor.getColumnIndex(Article.ARTICLE_TITLE)));
		article.setNickname(cursor.getString(cursor.getColumnIndex(Article.NICKNAME)));
		long time = Long.parseLong(cursor.getString(cursor.getColumnIndex(Article.WRITE_DATE)));
		article.setWriteDate(new Date(time));
		article.setCommentCount(Integer.parseInt(cursor.getString(cursor.getColumnIndex(Article.COMMENT_COUNT))));
		article.setReadCount(Integer.parseInt(cursor.getString(cursor.getColumnIndex(Article.READ_COUNT))));
		article.setCafeId(cursor.getString(cursor.getColumnIndex(Article.CAFE_ID)));
		int hidden = Integer.parseInt(cursor.getString(cursor.getColumnIndex(Article.HIDDEN)));
		if(hidden == 1) {
			article.setHidden(true);
		}else {
			article.setHidden(false);
		}
		int newArticle = Integer.parseInt(cursor.getString(cursor.getColumnIndex(Article.NEW_ARTICLE)));
		if(newArticle == 1) {
			article.setNewArticle(true);
		}else {
			article.setNewArticle(false);
		}
		
		return article;
	}
}
